# Copyright lowRISC contributors (OpenTitan project).
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0

import unittest
import zlib

from device_profile_data import extract_profile_data


class TestExtractProfileData(unittest.TestCase):

    def test_missing_profile_header(self):
        # Missing header.
        DEVICE_OUTPUT = """
I00001 coverage_test.c:37] Collecting coverage data.\r
|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\rI00002 ottf_main.c:100] Finished sw/device/tests/coverage_test.c\r
I00004 coverage_llvm.c:49] 0x00000000000021f394013fcb9ab28abed597d935c6d97871b5c22d4be3bf454ff545a1a3a088fb\r
I00005 coverage_llvm.c:55] 3952aa7a33c228d552a9b24f3bec051b44b406c4090b85b38cf6982e5287fb61c7a56d0c0e7b34c5\r
\x04\r
I00034 status.c:28] PASS!\r
"""  # noqa: E501
        with self.assertRaisesRegex(ValueError, ".*detect LLVM profile data.*"):
            extract_profile_data(DEVICE_OUTPUT)

    def test_incomplete_data(self):
        # 79 bytes of profile data with a bad checksum.
        DEVICE_OUTPUT = """
I00001 coverage_test.c:37] Collecting coverage data.\r
|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\rI00002 ottf_main.c:100] Finished sw/device/tests/coverage_test.c\r
I00003 coverage_llvm.c:40] LLVM profile data (length: 1184 bytes, CRC32: 0x79a3fcf1):\r
I00004 coverage_llvm.c:49] 0x00000000000021f394013fcb9ab28abed597d935c6d97871b5c22d4be3bf454ff545a1a3a088fb\r
I00005 coverage_llvm.c:55] 3952aa7a33c228d552a9b24f3bec051b44b406c4090b85b38cf6982e5287fb61c7a56d0c0e7b34c5\r
\x04\r
I00034 status.c:28] PASS!\r
"""  # noqa: E501
        with self.assertRaisesRegex(ValueError, "Length.*1184.*79"):
            extract_profile_data(DEVICE_OUTPUT)

    def test_extra_data(self):
        # 79 bytes of profile data with a bad checksum.
        DEVICE_OUTPUT = """
I00001 coverage_test.c:37] Collecting coverage data.\r
|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\rI00002 ottf_main.c:100] Finished sw/device/tests/coverage_test.c\r
I00003 coverage_llvm.c:40] LLVM profile data (length: 10 bytes, CRC32: 0x79a3fcf1):\r
I00004 coverage_llvm.c:49] 0x00000000000021f394013fcb9ab28abed597d935c6d97871b5c22d4be3bf454ff545a1a3a088fb\r
I00005 coverage_llvm.c:55] 3952aa7a33c228d552a9b24f3bec051b44b406c4090b85b38cf6982e5287fb61c7a56d0c0e7b34c5\r
\x04\r
I00034 status.c:28] PASS!\r
"""  # noqa: E501
        with self.assertRaisesRegex(ValueError, "Length.*10.*79"):
            extract_profile_data(DEVICE_OUTPUT)

    def test_bad_data(self):
        # LSB is incremented.
        DEVICE_OUTPUT = """
I00001 coverage_test.c:37] Collecting coverage data.\r
|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\rI00002 ottf_main.c:100] Finished sw/device/tests/coverage_test.c\r
I00003 coverage_llvm.c:40] LLVM profile data (length: 1184 bytes, CRC32: 0x79a3fcf1):\r
I00004 coverage_llvm.c:49] 0x00000000000021f394013fcb9ab28abed597d935c6d97871b5c22d4be3bf454ff545a1a3a088fb\r
I00005 coverage_llvm.c:55] 3952aa7a33c228d552a9b24f3bec051b44b406c4090b85b38cf6982e5287fb61c7a56d0c0e7b34c5\r
I00006 coverage_llvm.c:55] 21b5c39055cf3e522491837772d58214efb175afb67fa75921d375aff63d3170acbb0b258e4fbf9d\r
I00007 coverage_llvm.c:55] 71a8309b0df2e74ce77a7c5a7cc3c14c36b35552a3d8180c0c9ddd0e6ed93e91253b8051342b20b4\r
I00008 coverage_llvm.c:55] 5b00bc66f5fdf731fc858fa3be43ba74ac22d76cffd1068e5b686758a673f44f49901f04c5a8405e\r
I00009 coverage_llvm.c:55] f4113c55d8e64903086e9341fd35c05aeed3facf17810084057d386e0595d8319a245b08d1b7a5e7\r
I00010 coverage_llvm.c:55] f51b87840c3083725d906dda7801f6058cc6a9e2031feb0e20d852cd71f0bdbf1fdd52a7b75c7407\r
I00011 coverage_llvm.c:55] 973eb601ae27538bb483be5da633bbcd90e7ee0e40ca07cf7f486e28ca999a1a6df9275286d4ae3d\r
I00012 coverage_llvm.c:55] e15775281fed2ad11181648aad8734261abeadd492d1c8bcf5fd8a6514ffa66b380edac12d3bfe12\r
I00013 coverage_llvm.c:55] 1f196fb35e482501b905675ac17ede534dd32bdc220c24a5869b1af052b58e754971425f082834b9\r
I00014 coverage_llvm.c:55] 0baeb2a6272ff99760be528401bbde859d0de23c74061a1c72503d707b49cd818733e31243a44fdd\r
I00015 coverage_llvm.c:55] 1534b704e0a6ab8dd182da6817938e70e9ded660ded169c3025a2e95a73d34e6e07c39766ae7a71b\r
I00016 coverage_llvm.c:55] a4299ae6493291d78f6e493019a0edb36675080b9de3f3d60a36a3d48aeef7b4060da47929b3a32a\r
I00017 coverage_llvm.c:55] 1cd4c68fa17e9845f097e4918c0cce83af01f2e7e4de8c8ba916804f0a24bcf74f4d82f6482eea28\r
I00018 coverage_llvm.c:55] cfafd10860608b53370162999f95b2e487287f2c10208472cb527dda7802cc08e600000000000000\r
I00019 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
I00020 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
I00021 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000010000000000000000100020\r
I00022 coverage_llvm.c:55] b80000000000000000e5c91135ef4ad0040000000000000000000000010000000000000000100020\r
I00023 coverage_llvm.c:55] b000000000000000001e6f988c0f30fc690000000000000000000000010000000000000000100020\r
I00024 coverage_llvm.c:55] a80000000000000018033aa10a754487ea0000000000000000000000010000000000000000100020\r
I00025 coverage_llvm.c:55] a000000000000000182866785ba88630d10000000000000000000000020000000000000000100020\r
I00026 coverage_llvm.c:55] 900000000000002458432fb3b3752212ac0000000000000000000000010000000000000000100020\r
I00027 coverage_llvm.c:55] 88000000000000001855b0dadd552fc7f40000000000000000000000010000000000000000100020\r
I00028 coverage_llvm.c:55] 800000000000000018f68439af15ff54f00000000000000000000000030000000000000000100020\r
I00029 coverage_llvm.c:55] 680000000002442691b76b703b9eedfc350000000000000000000000010000000000000000100020\r
I00030 coverage_llvm.c:55] 600000000000000000e244489b389e5e0b0000000000000000000000010000000000000000100020\r
I00031 coverage_llvm.c:55] 5800000000000000189e484bc850eb41db00000000000000010000000020004c1400000000100020\r
I00032 coverage_llvm.c:55] 58000000000000024a0000000000000000000000000000000d000000000000000000000000000000\r
I00033 coverage_llvm.c:55] 0a00000000000000000000000000000007ff6c70726f665282\r
\x04\r
I00034 status.c:28] PASS!\r
"""  # noqa: E501
        with self.assertRaisesRegex(ValueError, "Checksum.*"):
            extract_profile_data(DEVICE_OUTPUT)

    def test_missing_eot(self):
        # Missing EOT character, wrong length, bad checksum.
        DEVICE_OUTPUT = """
I00001 coverage_test.c:37] Collecting coverage data.\r
|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\rI00002 ottf_main.c:100] Finished sw/device/tests/coverage_test.c\r
I00003 coverage_llvm.c:40] LLVM profile data (length: 1184 bytes, CRC32: 0x79a3fcf1):\r
I00031 coverage_llvm.c:55] 5800000000000000189e484bc850eb41db00000000000000010000000020004c1400000000100020\r
I00032 coverage_llvm.c:55] 58000000000000024a0000000000000000000000000000000d000000000000000000000000000000\r
\r
I00034 status.c:28] PASS!\r
"""  # noqa: E501
        with self.assertRaisesRegex(ValueError, ".*detect LLVM profile data.*"):
            extract_profile_data(DEVICE_OUTPUT)

    def test_bad_checksum(self):
        # Checksum is incremented.
        DEVICE_OUTPUT = """
I00001 coverage_test.c:37] Collecting coverage data.\r
|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\rI00002 ottf_main.c:100] Finished sw/device/tests/coverage_test.c\r
I00003 coverage_llvm.c:40] LLVM profile data (length: 1184 bytes, CRC32: 0x79a3fcf2):\r
I00004 coverage_llvm.c:49] 0x00000000000021f394013fcb9ab28abed597d935c6d97871b5c22d4be3bf454ff545a1a3a088fb\r
I00005 coverage_llvm.c:55] 3952aa7a33c228d552a9b24f3bec051b44b406c4090b85b38cf6982e5287fb61c7a56d0c0e7b34c5\r
I00006 coverage_llvm.c:55] 21b5c39055cf3e522491837772d58214efb175afb67fa75921d375aff63d3170acbb0b258e4fbf9d\r
I00007 coverage_llvm.c:55] 71a8309b0df2e74ce77a7c5a7cc3c14c36b35552a3d8180c0c9ddd0e6ed93e91253b8051342b20b4\r
I00008 coverage_llvm.c:55] 5b00bc66f5fdf731fc858fa3be43ba74ac22d76cffd1068e5b686758a673f44f49901f04c5a8405e\r
I00009 coverage_llvm.c:55] f4113c55d8e64903086e9341fd35c05aeed3facf17810084057d386e0595d8319a245b08d1b7a5e7\r
I00010 coverage_llvm.c:55] f51b87840c3083725d906dda7801f6058cc6a9e2031feb0e20d852cd71f0bdbf1fdd52a7b75c7407\r
I00011 coverage_llvm.c:55] 973eb601ae27538bb483be5da633bbcd90e7ee0e40ca07cf7f486e28ca999a1a6df9275286d4ae3d\r
I00012 coverage_llvm.c:55] e15775281fed2ad11181648aad8734261abeadd492d1c8bcf5fd8a6514ffa66b380edac12d3bfe12\r
I00013 coverage_llvm.c:55] 1f196fb35e482501b905675ac17ede534dd32bdc220c24a5869b1af052b58e754971425f082834b9\r
I00014 coverage_llvm.c:55] 0baeb2a6272ff99760be528401bbde859d0de23c74061a1c72503d707b49cd818733e31243a44fdd\r
I00015 coverage_llvm.c:55] 1534b704e0a6ab8dd182da6817938e70e9ded660ded169c3025a2e95a73d34e6e07c39766ae7a71b\r
I00016 coverage_llvm.c:55] a4299ae6493291d78f6e493019a0edb36675080b9de3f3d60a36a3d48aeef7b4060da47929b3a32a\r
I00017 coverage_llvm.c:55] 1cd4c68fa17e9845f097e4918c0cce83af01f2e7e4de8c8ba916804f0a24bcf74f4d82f6482eea28\r
I00018 coverage_llvm.c:55] cfafd10860608b53370162999f95b2e487287f2c10208472cb527dda7802cc08e600000000000000\r
I00019 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
I00020 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
I00021 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000010000000000000000100020\r
I00022 coverage_llvm.c:55] b80000000000000000e5c91135ef4ad0040000000000000000000000010000000000000000100020\r
I00023 coverage_llvm.c:55] b000000000000000001e6f988c0f30fc690000000000000000000000010000000000000000100020\r
I00024 coverage_llvm.c:55] a80000000000000018033aa10a754487ea0000000000000000000000010000000000000000100020\r
I00025 coverage_llvm.c:55] a000000000000000182866785ba88630d10000000000000000000000020000000000000000100020\r
I00026 coverage_llvm.c:55] 900000000000002458432fb3b3752212ac0000000000000000000000010000000000000000100020\r
I00027 coverage_llvm.c:55] 88000000000000001855b0dadd552fc7f40000000000000000000000010000000000000000100020\r
I00028 coverage_llvm.c:55] 800000000000000018f68439af15ff54f00000000000000000000000030000000000000000100020\r
I00029 coverage_llvm.c:55] 680000000002442691b76b703b9eedfc350000000000000000000000010000000000000000100020\r
I00030 coverage_llvm.c:55] 600000000000000000e244489b389e5e0b0000000000000000000000010000000000000000100020\r
I00031 coverage_llvm.c:55] 5800000000000000189e484bc850eb41db00000000000000010000000020004c1400000000100020\r
I00032 coverage_llvm.c:55] 58000000000000024a0000000000000000000000000000000d000000000000000000000000000000\r
I00033 coverage_llvm.c:55] 0a00000000000000000000000000000007ff6c70726f665281\r
\x04\r
I00034 status.c:28] PASS!\r
"""  # noqa: E501
        with self.assertRaisesRegex(ValueError, "Checksum.*"):
            extract_profile_data(DEVICE_OUTPUT)

    def test_good_data(self):
        DEVICE_OUTPUT = """
I00001 coverage_test.c:37] Collecting coverage data.\r
|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\r|\r/\r-\r\\rI00002 ottf_main.c:100] Finished sw/device/tests/coverage_test.c\r
I00003 coverage_llvm.c:40] LLVM profile data (length: 1184 bytes, CRC32: 0x79a3fcf1):\r
I00004 coverage_llvm.c:49] 0x00000000000021f394013fcb9ab28abed597d935c6d97871b5c22d4be3bf454ff545a1a3a088fb\r
I00005 coverage_llvm.c:55] 3952aa7a33c228d552a9b24f3bec051b44b406c4090b85b38cf6982e5287fb61c7a56d0c0e7b34c5\r
I00006 coverage_llvm.c:55] 21b5c39055cf3e522491837772d58214efb175afb67fa75921d375aff63d3170acbb0b258e4fbf9d\r
I00007 coverage_llvm.c:55] 71a8309b0df2e74ce77a7c5a7cc3c14c36b35552a3d8180c0c9ddd0e6ed93e91253b8051342b20b4\r
I00008 coverage_llvm.c:55] 5b00bc66f5fdf731fc858fa3be43ba74ac22d76cffd1068e5b686758a673f44f49901f04c5a8405e\r
I00009 coverage_llvm.c:55] f4113c55d8e64903086e9341fd35c05aeed3facf17810084057d386e0595d8319a245b08d1b7a5e7\r
I00010 coverage_llvm.c:55] f51b87840c3083725d906dda7801f6058cc6a9e2031feb0e20d852cd71f0bdbf1fdd52a7b75c7407\r
I00011 coverage_llvm.c:55] 973eb601ae27538bb483be5da633bbcd90e7ee0e40ca07cf7f486e28ca999a1a6df9275286d4ae3d\r
I00012 coverage_llvm.c:55] e15775281fed2ad11181648aad8734261abeadd492d1c8bcf5fd8a6514ffa66b380edac12d3bfe12\r
I00013 coverage_llvm.c:55] 1f196fb35e482501b905675ac17ede534dd32bdc220c24a5869b1af052b58e754971425f082834b9\r
I00014 coverage_llvm.c:55] 0baeb2a6272ff99760be528401bbde859d0de23c74061a1c72503d707b49cd818733e31243a44fdd\r
I00015 coverage_llvm.c:55] 1534b704e0a6ab8dd182da6817938e70e9ded660ded169c3025a2e95a73d34e6e07c39766ae7a71b\r
I00016 coverage_llvm.c:55] a4299ae6493291d78f6e493019a0edb36675080b9de3f3d60a36a3d48aeef7b4060da47929b3a32a\r
I00017 coverage_llvm.c:55] 1cd4c68fa17e9845f097e4918c0cce83af01f2e7e4de8c8ba916804f0a24bcf74f4d82f6482eea28\r
I00018 coverage_llvm.c:55] cfafd10860608b53370162999f95b2e487287f2c10208472cb527dda7802cc08e600000000000000\r
I00019 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
I00020 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000000000000000000000000000\r
I00021 coverage_llvm.c:55] 00000000000000000000000000000000000000000000000000000000010000000000000000100020\r
I00022 coverage_llvm.c:55] b80000000000000000e5c91135ef4ad0040000000000000000000000010000000000000000100020\r
I00023 coverage_llvm.c:55] b000000000000000001e6f988c0f30fc690000000000000000000000010000000000000000100020\r
I00024 coverage_llvm.c:55] a80000000000000018033aa10a754487ea0000000000000000000000010000000000000000100020\r
I00025 coverage_llvm.c:55] a000000000000000182866785ba88630d10000000000000000000000020000000000000000100020\r
I00026 coverage_llvm.c:55] 900000000000002458432fb3b3752212ac0000000000000000000000010000000000000000100020\r
I00027 coverage_llvm.c:55] 88000000000000001855b0dadd552fc7f40000000000000000000000010000000000000000100020\r
I00028 coverage_llvm.c:55] 800000000000000018f68439af15ff54f00000000000000000000000030000000000000000100020\r
I00029 coverage_llvm.c:55] 680000000002442691b76b703b9eedfc350000000000000000000000010000000000000000100020\r
I00030 coverage_llvm.c:55] 600000000000000000e244489b389e5e0b0000000000000000000000010000000000000000100020\r
I00031 coverage_llvm.c:55] 5800000000000000189e484bc850eb41db00000000000000010000000020004c1400000000100020\r
I00032 coverage_llvm.c:55] 58000000000000024a0000000000000000000000000000000d000000000000000000000000000000\r
I00033 coverage_llvm.c:55] 0a00000000000000000000000000000007ff6c70726f665281\r
\x04\r
I00034 status.c:28] PASS!\r
"""  # noqa: E501
        raw_profile_data = extract_profile_data(DEVICE_OUTPUT)
        self.assertEqual(len(raw_profile_data), 1184)
        self.assertEqual(zlib.crc32(raw_profile_data), 0x79a3fcf1)


if __name__ == '__main__':
    unittest.main()
